<?php


namespace App\Common;


use EasySwoole\Component\Singleton;
use EasySwoole\EasySwoole\Config;
use EasySwoole\Pool\Manager;

class Redis
{
    use Singleton;
    /**
     * @var null
     * @var  \EasySwoole\Redis\Redis
     * redis连接对象
     */
    protected $redisPool = null;


    /**
     * Redis constructor.
     * @throws \Throwable
     */
    public function __construct()
    {
        if (!$this->singleton()) {
            $redisName = Config::getInstance()->getConf('REDIS_POOL_NAME');
            $redisPoolName = $redisName['default'];
            if ($redisName['is_rand']) {
                $redisPoolName = array_rand($redisName['pool_name']);
            }
            $redis = Manager::getInstance()->get($redisPoolName);
            $this->redisPool = $redis->getObj();
        }
    }

    /**
     * @param $key
     * @return mixed
     */
    public function get($key)
    {
        return $this->redisPool->get($key);
    }

    /**
     * @param $key string key
     * @param $val string 值
     * @param int $timeout 时间秒
     * @return mixed
     */
    public function set($key, $val, $timeout = 0)
    {
        return $this->redisPool->set($key, $val, (int)$timeout);
    }

    /**
     * @param $key
     * @return mixed
     * 获取队列值
     */
    public function lpop($key)
    {
        $res = $this->redisPool->lpop($key);
        $result = json_decode($res, true);
        return is_null($result) ? $res : $result;
    }

    /**
     * @param $key
     * @param $value
     * @return mixed
     * 推送值到redis
     */
    public function rpush($key, $value)
    {
        if (is_array($value)) {
            $value = json_encode($value);
        }
        return $this->redisPool->rpush($key, $value);
    }


//解决队列为空出现的问题 替代lpop

    /**
     * @param $key
     * @param $timeout int 超时时间 如果有数据马上返回 没有就堵塞的时间 在返回 nil
     * @return mixed
     */
    public function blpop($key, int $timeout)
    {
        $res = $this->redisPool->blpop($key, (int)$timeout);
        $result = json_decode($res, true);
        return is_null($result) ? $res : $result;
    }

    /**
     * @param $key
     * @param $timeout int 超时时间 如果有数据马上返回 没有就堵塞的时间 在返回 nil1
     * @return mixed
     */
    public function brpop($key)
    {
        $res = $this->redisPool->brpop($key, (int)$key);
        $result = json_decode($res, true);
        return is_null($result) ? $res : $result;
    }

    /*********************redis延时队列***************************/


    /**
     * @param $delay int 延时秒数
     * @param $key  string 集合名称
     * @param string|array $data 投递的数据
     * @return mixed
     *  redis延时队列消息投递
     */
    public function later($delay, $key, $data)
    {
        $data = is_array($data) ? json_encode($data) : $data;
        $score1 = time() + $delay;
        return $this->redisPool->zAdd($key, $score1, $data);
    }

    /**
     * @param $key
     * @return mixed
     * 返回延时消息
     */
    public function pop($key)
    {
        $res = $this->redisPool->zRangeByScore($key, 0, time(), ['withScores' => true, 'limit' => array(0, 1)]);
        return array_keys($res)[0];
    }

    /**
     * @param $key string key
     * @param $data string 获取延时消息的数据
     * @return mixed
     * 删除延时消息
     */
    public function remove($key, $data)
    {
        return $this->redisPool->zRem($key, $data);
    }


    //todo 需要什么方法就添加什么方法
    private function singleton()
    {
        if (!$this->redisPool) {
            return false;
        }
        return true;
    }

    public function __destruct()
    {
        // TODO: Implement __destruct() method.
    }

}
